﻿namespace Microsoft.Tools.WixDeployment.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using Microsoft.Tools.WindowsInstallerXml;
    using System.Xml.Linq;

    /// <summary>
    /// Provides commons utility funtions.
    /// </summary>
    public class AttributeParser
    {
        private HashSet<string> RequiredAttributes { get; set; }
        private HashSet<string> OptionalAttributes { get; set; }
        private CompilerExtension compilerExtension;

        public AttributeParser(CompilerExtension compilerExtension, string[] requiredAttributes, string[] optionalAttributes)            
        {
            this.compilerExtension = compilerExtension;    
            RequiredAttributes = new HashSet<string>(requiredAttributes);
            OptionalAttributes = new HashSet<string>(optionalAttributes);
        }

        public AttributeParser(CompilerExtension compilerExtension, string[] requiredAttributes)
            : this(compilerExtension, requiredAttributes, new string[] { }) { }

        public Dictionary<string, string> ParseAttributes(XmlNode node, Func<XmlAttribute, bool> condition)
        {
            if (node == null) return null;

            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            Dictionary<string, string> parsedResult = new Dictionary<string, string>();

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (condition != null && condition(attrib))
                {                    
                    if (this.RequiredAttributes.Contains(attrib.LocalName) || OptionalAttributes.Contains(attrib.LocalName))
                    {
                        parsedResult.Add(attrib.LocalName, (attrib.LocalName == Constants.Id) 
                            ? compilerExtension.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib)
                            : compilerExtension.Core.GetAttributeValue(sourceLineNumbers, attrib));                        
                    }
                    else
                    {
                        compilerExtension.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                    }
                }
                else
                {
                    compilerExtension.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (RequiredAttributes.Except(parsedResult.Keys).Any())
            {
                compilerExtension.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, RequiredAttributes.Except(parsedResult.Keys).First()));
            }
            
            OptionalAttributes.Except(parsedResult.Keys).ToList()
                              .ForEach(s => parsedResult.Add(s, null));
            
            return parsedResult;
        }
    }
}
